package jp.co.hcs.attendancemanagement.inputtableb.action;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jp.co.hcs.attendancemanagement.AMConstants;
import jp.co.hcs.attendancemanagement.action.AMLookupDispatchAction;
import jp.co.hcs.attendancemanagement.data.entity.Project;
import jp.co.hcs.attendancemanagement.data.entity.Work;
import jp.co.hcs.attendancemanagement.data.entity.ex.EffortActualParameter;
import jp.co.hcs.attendancemanagement.exception.AMException;
import jp.co.hcs.attendancemanagement.inputtableb.actionform.InputTableBForm;
import jp.co.hcs.attendancemanagement.inputtableb.logic.CheckProjectCodeLogic;
import jp.co.hcs.attendancemanagement.inputtableb.logic.CheckWorkCodeLogic;
import jp.co.hcs.attendancemanagement.inputtableb.logic.InputTableBLogic;
import jp.co.hcs.attendancemanagement.inputtableb.logic.dto.ProjectEffortInfoDTO;
import jp.co.hcs.attendancemanagement.inputtableb.logic.dto.WorkDayDTO;
import jp.co.hcs.attendancemanagement.util.StringUtil;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.util.MessageResources;

/**
 * The Class InputTableBAction.
 */
public class InputTableBAction extends AMLookupDispatchAction {

  /** The Constant SUCCESS. */
  private final static String SUCCESS = "success";

  /** The Constant ERROR. */
  private final static String ERROR = "error";

  /** The msg resource. */
  private MessageResources msgResource = MessageResources
      .getMessageResources("MessageResourcesForStruts");

  /*
   * (non-Javadoc)
   * 
   * @see org.apache.struts.actions.LookupDispatchAction#getKeyMethodMap()
   */
  protected Map getKeyMethodMap() {
    Map<String, String> map = new HashMap<String, String>();
    map.put("inputtableb.button.save", "save");
    map.put("inputtableb.button.show", "show");
    map.put("inputtableb.button.export", "export");
    map.put("inputtableb.button.print", "print");
    map.put("inputtableb.button.deleteproject", "deleteProject");
    map.put("inputtableb.button.addproject", "addProject");
    return map;
  }

  /**
   * Save.
   * 
   * @param mapping the mapping
   * @param form the form
   * @param request the request
   * @param response the response
   * @return the action forward
   * @throws Exception the exception
   */
  public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request,
      HttpServletResponse response) throws Exception {
    // if (isTokenValid(request)) {
    InputTableBForm inputTableBForm = (InputTableBForm) form;
    int dayOfMonth =
        StringUtil.getDaysInMonth(Integer.parseInt(inputTableBForm.getInputYear()), Integer
            .parseInt(inputTableBForm.getInputMonth()));
    
    String selectPeriod = inputTableBForm.getInputYear() + inputTableBForm.getInputMonth();
    EffortActualParameter effortActualParameter = new EffortActualParameter();
    effortActualParameter.setEmployerCode((String) request.getSession().getAttribute(
        AMConstants.USER_LOGGED_IN));
    effortActualParameter.setSelectPeriod(selectPeriod);

    InputTableBLogic inputTableBLogic = InputTableBLogic.getInstance();
    CheckProjectCodeLogic checkProjectCodeLogic = CheckProjectCodeLogic.getInstance();
    CheckWorkCodeLogic checkWorkCodeLogic = CheckWorkCodeLogic.getInstance();

    ActionMessages errors = new ActionMessages();
    boolean checkValid = true;
    Project project;
    Work workObj;

    for (ProjectEffortInfoDTO p : inputTableBForm.getProjectEffortInfoDTOList()) {
      project = checkProjectCodeLogic.checkProjectCodeExisting(p.getProjectCode(), p.getSeri());
      if (project == null) {
        checkValid = false;
        errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("Alarm.W1058.error",
            p.getProjectCode()+p.getSeri()));
        break;
      }
    }
    if (checkValid) {
      for (ProjectEffortInfoDTO p : inputTableBForm.getProjectEffortInfoDTOList()) {
        workObj = checkWorkCodeLogic.checkWorkCodeExisting(p.getWorkCode());
        if (workObj == null) {
          checkValid = false;
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("Alarm.W1058.error",
              p.getWorkCode()));
          break;
        }
      }
    }
    // check existing project number and work code
    boolean outerLoopBreak = false;
    ProjectEffortInfoDTO p1;
    ProjectEffortInfoDTO p2;
    List<ProjectEffortInfoDTO> projectEffortList = inputTableBForm.getProjectEffortInfoDTOList();
    for (int i = 0; i < projectEffortList.size() - 1; i++) {
      p1 = projectEffortList.get(i);
      for (int j = i + 1; j < projectEffortList.size(); j++) {
        p2 = projectEffortList.get(j);
        if (p1.getProjectCode().equals(p2.getProjectCode()) && p1.getSeri().equals(p2.getSeri())
            && p1.getWorkCode().equals(p2.getWorkCode())) {
          errors.add(ActionErrors.GLOBAL_MESSAGE, new ActionMessage("Alarm.W1096.error",
              msgResource.getMessage("Alarm.W1096.error.value")));
          outerLoopBreak = true;
          break;
        }
      }
      if (outerLoopBreak) {
        break;
      }
    }

    if (!errors.isEmpty()) {
      saveErrors(request, errors);
      return mapping.findForward(SUCCESS);
    }

    // reset the token
    // resetToken(request);
    inputTableBLogic.setProjectChangeFlag(inputTableBForm.getProjectEffortInfoDTOList());
    inputTableBLogic.setValueChangeFlags(inputTableBForm.getProjectEffortInfoDTOList());
    errors = inputTableBLogic.saveProjectEffortInfoList(inputTableBForm.getProjectEffortInfoDTOList(),
        effortActualParameter);
    
    String employeeCode = (String) request.getSession().getAttribute(
            AMConstants.USER_LOGGED_IN);
    if (!errors.isEmpty()) {
        saveErrors(request, errors);
        setupForProjectInfoList(inputTableBForm,inputTableBLogic, employeeCode, dayOfMonth);
        return mapping.findForward(SUCCESS);
      }
    inputTableBForm.setbChanged(false);
    inputTableBForm.setbShowDelete(true);
    // inputTableBForm.setb
    // }
    return mapping.findForward(SUCCESS);
  }

  /**
   * Check data change.
   * 
   * @param form the form
   * @return true, if successful
   */
  private boolean checkDataChange(InputTableBForm form) {

    boolean isChange = false;
    for (ProjectEffortInfoDTO p : form.getProjectEffortInfoDTOList()) {
      // if(p.isbAdd())
      // {
      // break;
      // }
      if (p.isbChanged()) {
        isChange = true;
        break;
      } else {
        for (WorkDayDTO w : p.getWorkDayDTOList()) {
          if (w.isbChanged()) {
            isChange = true;
            break;
          }
        }
      }
    }
    return isChange;
  }

  /**
   * Show.
   * 
   * @param mapping the mapping
   * @param form the form
   * @param request the request
   * @param response the response
   * @return the action forward
   * @throws Exception the exception
   */
  public ActionForward show(ActionMapping mapping, ActionForm form, HttpServletRequest request,
      HttpServletResponse response) throws Exception {

    ActionForward forward = mapping.findForward(SUCCESS);
    InputTableBForm inputTableBForm = (InputTableBForm) form;
    inputTableBForm.setbShowAdd(true);
    inputTableBForm.setbShowDelete(true);
    inputTableBForm.setbChanged(false);
    int dayOfMonth =
          StringUtil.getDaysInMonth(Integer.parseInt(inputTableBForm.getInputYear()), Integer
              .parseInt(inputTableBForm.getInputMonth()));
    inputTableBForm.setActualEffortYearMonth(inputTableBForm.getInputYear()
          + inputTableBForm.getInputMonth());
      String[] dayNameArray = new String[dayOfMonth];
	  for (int i = 0; i < dayNameArray.length; i++) {
	    dayNameArray[i] =
	        StringUtil.dayNameOfWeekMap.get(StringUtil.getDayName(Integer.parseInt(inputTableBForm
	            .getInputYear()), Integer.parseInt(inputTableBForm.getInputMonth()), i + 1));
	  }
      inputTableBForm.setDayNameArray(dayNameArray);

      inputTableBForm.setDayNumberOfMonth(dayOfMonth);
      InputTableBLogic inputTableBLogic = InputTableBLogic.getInstance();
      String employeeCode = (String) request.getSession().getAttribute(
              AMConstants.USER_LOGGED_IN);
      setupForProjectInfoList(inputTableBForm,inputTableBLogic, employeeCode, dayOfMonth);
//        inputTableBLogic.setProjectChangeFlag(inputTableBForm.getProjectEffortInfoDTOList());
//        inputTableBLogic.setValueChangeFlags(inputTableBForm.getProjectEffortInfoDTOList());
//        
//        if (checkDataChange(inputTableBForm)) {
//          inputTableBForm.setbChanged(true);
//        } else {
//          inputTableBForm.setbChanged(false);
//        }
    return forward;
  }

  /**
   * Export.
   * 
   * @param mapping the mapping
   * @param form the form
   * @param request the request
   * @param response the response
   * @return the action forward
   * @throws Exception the exception
   */
  public ActionForward export(ActionMapping mapping, ActionForm form, HttpServletRequest request,
      HttpServletResponse response) throws Exception {
    //
    if (isTokenValid(request)) {
      // reset the token
      resetToken(request);

      InputTableBForm inputTableBForm = (InputTableBForm) form;
      MessageResources msgResource = getResources(request);
      // ServletOutputStream out = response.getOutputStream();
      // response.setContentType("application/text; charset=utf-8");
      response.setContentType("text/csv; charset=UTF-8");
      PrintWriter out = response.getWriter();

      String nameFile =
          inputTableBForm.getEmployerCode() + "_" + inputTableBForm.getInputYear()
              + inputTableBForm.getInputMonth() + "_B.csv";
      response.setHeader("Content-disposition", "filename=\"" + nameFile + "\"");
      // OutputStream output = response.getOutputStream();
      // Writer out = new BufferedWriter(new
      // OutputStreamWriter(output,"UTF-8"));

      // Header
      // input period
      // out.write(line);
      out.write(msgResource.getMessage("inputtableb.label.yearchosing") + ", "
          + msgResource.getMessage("inputtableb.label.monthchosing"));
      out.write("\n");
      out.write(inputTableBForm.getInputYear() + ", " + inputTableBForm.getInputMonth());
      out.write("\n");
      out.write("\n");

      // employee information
      out.write(msgResource.getMessage("export.csv.title.employeecode") + ", "
              + msgResource.getMessage("export.csv.title.employeename") + ", "
              + msgResource.getMessage("export.csv.title.employeedepartment") + ", "
              + msgResource.getMessage("export.csv.title.employeedivision"));
      out.write("\n");
      out.write(inputTableBForm.getEmployerCode() + ", " + inputTableBForm.getEmployerName() + ", "
          + inputTableBForm.getDepartmentName() + ", " + inputTableBForm.getDivisionName());
      out.write("\n");
      out.write("\n");

      // projectInfo table Header
      out.write(msgResource.getMessage("inputtableb.table.column.projectcode") + ", "
          + msgResource.getMessage("inputtableb.table.column.seri") + ", "
          + msgResource.getMessage("inputtableb.table.column.projectname") + ", "
          + msgResource.getMessage("inputtableb.table.column.workcode") + ", "
          + msgResource.getMessage("inputtableb.table.column.workname") + ", "
          + msgResource.getMessage("inputtableb.table.column.subtotaltime") + ", ");
      int dayOfMonth = inputTableBForm.getDayNameArray().length;
      for (int i = 0; i < dayOfMonth; i++) {
        if (i != dayOfMonth - 1) {
          out.write(i + 1 + ", ");
        } else {
          out.write(i + 1 + "\n");
        }
      }
      // write day names
      out.write(",,,,,,");
      for (int i = 0; i < dayOfMonth; i++) {
        if (i != dayOfMonth - 1) {
          out.write(inputTableBForm.getDayNameArray()[i] + ", ");
        } else {
          out.write(inputTableBForm.getDayNameArray()[i] + "\n");
        }
      }
//      List<Integer> totalValueList = new ArrayList<Integer>();
//      totalValueList.add(0);
//      for (int i = 0; i < dayOfMonth; i++) {
//    	  totalValueList.add(0);
//      }
      int[] totalValueArray = new int[dayOfMonth+1];
     
      for (ProjectEffortInfoDTO p : inputTableBForm.getProjectEffortInfoDTOList()) {
    	  String timeValue = null;
    	  int dayNumber = 0;
          for (WorkDayDTO w : p.getWorkDayDTOList()) {
        	dayNumber  = Integer.parseInt(w.getDayNumber());
            timeValue = w.getWorkTime();
            totalValueArray[dayNumber] += StringUtil.convertTimesToMinutes(timeValue); 
          }
        }
      int allTotalTime = 0;
      for (ProjectEffortInfoDTO p : inputTableBForm.getProjectEffortInfoDTOList()) {
        out.write(p.getProjectCode() + ", " + p.getSeri() + ", " + p.getProjectName() + ", "
            + p.getWorkCode() + ", " + p.getWorkName() + ", ");
        
        //total time for each work
        int totalTime = 0;
        for (WorkDayDTO w : p.getWorkDayDTOList()) {
        	totalTime += StringUtil.convertTimesToMinutes(w.getWorkTime()); 
        }
        allTotalTime += totalTime;
        out.write(StringUtil.caculateTotalTime(totalTime) + ", ");
        
        for (WorkDayDTO w : p.getWorkDayDTOList()) {
          out.write(w.getWorkTime() + ", ");
        }
        out.write("\n");
      }
      totalValueArray[0] = allTotalTime;
      
      //last total value line
      out.write(",,,,");
      out.write(msgResource.getMessage("inputtableb.table.column.totaltime"));
      out.write(", ");
      
      for(int i=0; i < totalValueArray.length;i++){
    	  out.write(StringUtil.caculateTotalTime(totalValueArray[i]));
    	  if(i <totalValueArray.length - 1){
    		  out.write(", ");
    	  }
      }
      
      out.flush();
      out.close();
    }
    return null;
  }

  /**
   * Prints the.
   * 
   * @param mapping the mapping
   * @param form the form
   * @param request the request
   * @param response the response
   * @return the action forward
   * @throws Exception the exception
   */
  public ActionForward print(ActionMapping mapping, ActionForm form, HttpServletRequest request,
      HttpServletResponse response) throws Exception {
    return mapping.findForward(SUCCESS);
  }

  /**
   * Delete project.
   * 
   * @param mapping the mapping
   * @param form the form
   * @param request the request
   * @param response the response
   * @return the action forward
   * @throws Exception the exception
   */
  public ActionForward deleteProject(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response) throws Exception {
    InputTableBForm inputTableBForm = (InputTableBForm) form;
    List<ProjectEffortInfoDTO> projectEffortInfoDTOList =
        inputTableBForm.getProjectEffortInfoDTOList();
    InputTableBLogic inputTableBLogic = InputTableBLogic.getInstance();
    inputTableBLogic.deteteProjectEffortInfoList(projectEffortInfoDTOList);
    return mapping.findForward(SUCCESS);
  }

  /**
   * Adds the project.
   * 
   * @param mapping the mapping
   * @param form the form
   * @param request the request
   * @param response the response
   * @return the action forward
   * @throws Exception the exception
   */
  public ActionForward addProject(ActionMapping mapping, ActionForm form,
      HttpServletRequest request, HttpServletResponse response) throws Exception {
    InputTableBForm inputTableBForm = (InputTableBForm) form;
    inputTableBForm.setbShowDelete(false);
    InputTableBLogic inputTableBLogic = InputTableBLogic.getInstance();
    int dayOfMonth =
        StringUtil.getDaysInMonth(Integer.parseInt(inputTableBForm.getInputYear()), Integer
            .parseInt(inputTableBForm.getInputMonth()));
    String selectPeriod = inputTableBForm.getInputYear() + inputTableBForm.getInputMonth();
    EffortActualParameter effortActualParameter = new EffortActualParameter();
    effortActualParameter.setEmployerCode((String) request.getSession().getAttribute(
        AMConstants.USER_LOGGED_IN));
    effortActualParameter.setSelectPeriod(selectPeriod);
    inputTableBLogic.initAddProjectEffortInfo(inputTableBForm.getProjectEffortInfoDTOList(),
        dayOfMonth, effortActualParameter, (String) request.getSession().getAttribute(
            AMConstants.USER_LOGGED_IN));
    inputTableBForm.setbChanged(true);
    return mapping.findForward(SUCCESS);
  }
  
  private void setupForProjectInfoList(InputTableBForm inputTableBForm, InputTableBLogic inputTableBLogic,String employeeCode, int dayOfMonth) throws AMException{
//	  inputTableBForm.setOldActualEffortYearMonth(inputTableBForm.getActualEffortYearMonth());
      String selectPeriod = inputTableBForm.getInputYear() + inputTableBForm.getInputMonth();

      EffortActualParameter effortActualParameter = new EffortActualParameter();
      effortActualParameter.setEmployerCode(employeeCode);
      
      effortActualParameter.setSelectPeriod(selectPeriod);
      List<ProjectEffortInfoDTO> projectEffortInfoDTOList =
          inputTableBLogic.getProjectEffortInfoList(effortActualParameter);
      inputTableBForm.setProjectEffortInfoDTOList(projectEffortInfoDTOList);
      inputTableBForm.setDisableDaysList(inputTableBLogic.setDisableDaysList(
          effortActualParameter, dayOfMonth));
      inputTableBLogic.updateDataActualEffortDateToEffortInfo(inputTableBForm
          .getProjectEffortInfoDTOList(), effortActualParameter, dayOfMonth);
      inputTableBLogic.setHolidayExLineList(inputTableBForm.getHolidayExLineList(),
      		effortActualParameter, dayOfMonth);
  }
}
